package com.ruoyi.consumer.controller.wallet.walletOperationFactory;

import ch.qos.logback.classic.Logger;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.consumer.aop.annotation.RecordOpeate;
import com.ruoyi.consumer.controller.facilit.api.APIService;
import com.ruoyi.consumer.controller.facilit.fill.BigDataItem;
import com.ruoyi.consumer.controller.facilit.fill.DataItem;
import com.ruoyi.consumer.controller.facilit.fill.FillService;
import com.ruoyi.consumer.controller.wallet.WalletService;
import com.ruoyi.consumer.domain.*;
import com.ruoyi.consumer.domain.order.PayOrderDTO;
import com.ruoyi.consumer.service.impl.*;
import com.ruoyi.consumer.utils.JsonUtils;
import com.ruoyi.consumer.utils.fill.JsonParserExample;
import io.jsonwebtoken.lang.Assert;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Component
public class IndividualUserStrategy implements DeductionStrategy {


    private static final Logger logger = (Logger) LoggerFactory.getLogger(JsonUtils.class);

    @Autowired
    private CUserServiceImpl userService;

    @Autowired
    private CFillingFacilitServiceImpl fillingFacilitService;

    @Autowired
    private CWalletPersonServiceImpl walletPersonService;

    @Autowired
    private WalletService walletService;

    @Autowired
    private CRequirementServiceImpl requirementService;

    @Autowired
    private CDealPersonServiceImpl dealPersonService;

    @Autowired
    private CUnitPriceServiceImpl cUnitPriceService;

    @Autowired
    private CDeviceOrdersServiceImpl cDeviceOrdersService;

    @Autowired
    private APIService apiService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private FillService fillService;


    @Override
    @RecordOpeate(desc = "个人下单" )
    public Object takeOrder(Integer facilitId, Integer userId, Long amount, String snNumber) throws IOException {

        //查询设备信息
        CFillingFacilit fillingFacilit = fillingFacilitService.selectCFillingFacilitByFacilitId(facilitId);
        Assert.notNull(fillingFacilit, "设备信息不存在");

        //判断是否为待机状态
        Boolean waiting = apiService.isWaiting(fillingFacilit.getFacilitSn(), redisCache.getCacheObject("token:" + "authorizerAccessToken"));
        Assert.isTrue(waiting, "加注机不在待机状态不能下单");

        //查询单价
        List<CUnitPrice> cUnitPrices = cUnitPriceService.selectCUnitPriceList(new CUnitPrice());
        Assert.notNull(cUnitPrices, "单价不存在");


        //构建支付对象
        PayOrderDTO OrderDTO = new PayOrderDTO();
        OrderDTO.setEquipmentName(fillingFacilit.getFacilitName());
        OrderDTO.setSn(fillingFacilit.getFacilitSn());
        OrderDTO.setOrderVol(Double.valueOf(amount) / 1000);
        OrderDTO.setOrderPrice(Double.valueOf(cUnitPrices.get(0).getUnitVip()) / 100);
        //转换后的金额
        OrderDTO.setOrderMoney(OrderDTO.getOrderVol() * OrderDTO.getOrderPrice());
        OrderDTO.setOrderTitle("掌上快运加注");
        OrderDTO.setOrderType(2);
        OrderDTO.setCreateTime(new Date());
        OrderDTO.setSnNumber(snNumber);
        OrderDTO.setPayType("weixin");

        // 实现个人用户的扣款逻辑
        // 1. 查询用户余额
        CUser user = userService.selectCUserByUserId(userId);
        Assert.notNull(user, "用户不存在");

        CWalletPerson walletPerson = walletPersonService.selectCWalletPersonByUserId(userId);
        Assert.notNull(walletPerson, "用户钱包不存在");
//        System.out.println("walletPerson更新前信息: " + walletPerson);

        // 2. 判断余额是否足够
        Assert.isTrue(walletPerson.getWalletFree() >= amount, "钱包余液不足");

        // 4. 更新钱包交易记录....
        AjaxResult ajaxResult = walletService.expensePersonWallet(userId, amount);
        Assert.isTrue(ajaxResult.get("code").equals(200), "扣款失败");
        Integer dealId = (Integer) ajaxResult.get("cDealPersonId");
        String s1 = apiService.payOrder(OrderDTO, redisCache.getCacheObject("token:" + "authorizerAccessToken"));

        String orderId = null;
        try {
            String jsonString = s1; // 您的 JSON 字符串

            ObjectMapper mapper = new ObjectMapper();

            // 解析 JSON 字符串为 Map
            Map<String, Object> jsonMap = mapper.readValue(jsonString, Map.class);

            System.out.println("jsonMap" + jsonMap);

            // 获取 datas 对象
            Map<String, Object> datas = (Map<String, Object>) jsonMap.get("datas");

            System.out.println("datas" + datas);
            // 获取 manage 对象
            if (datas != null) {
                orderId = datas.get("id").toString();

                // 现在 manage 包含您需要的信息
                System.out.println("orderId" + orderId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //创建实际订单
        CDeviceOrders deviceOrders = new CDeviceOrders();
        deviceOrders.setSn(fillingFacilit.getFacilitSn());
        deviceOrders.setFillerId(orderId.toString());
        deviceOrders.setOrderFilled(0L);
        deviceOrders.setOrderFilledMoney(0);
        deviceOrders.setOrderMoney(0);
        deviceOrders.setOrderPrice(cUnitPrices.get(0).getUnitTemporary());
        deviceOrders.setOrderType(2);
        deviceOrders.setSnNumber(snNumber);
        deviceOrders.setStatus(0);

        CRequirement cRequirement = new CRequirement();
        cRequirement.setConsumerId(userId);
        cRequirement.setStatus(1);
        List<CRequirement> requirement = requirementService.selectCRequirementList(cRequirement);
        if (!requirement.isEmpty()) {
            deviceOrders.setRequireId(requirement.get(0).getRequireId());
        }
        int i1 = cDeviceOrdersService.insertCDeviceOrders(deviceOrders);
        Assert.isTrue(i1 > 0, "添加实际订单失败");



        CDeviceOrders deviceOrder = cDeviceOrdersService.selectCDeviceOrdersByDeviceOrderId(deviceOrders.getDeviceOrderId());
        Assert.notNull(deviceOrder, "订单不存在");

        CDealPerson dealPerson = dealPersonService.selectCDealPersonByDealRecordId(dealId);
        Assert.notNull(dealPerson, "交易记录不存在");

        dealPerson.setDealFacilitNum(deviceOrder.getSn());
        dealPerson.setDeviceOrderId(deviceOrder.getDeviceOrderId());
        int i2 = dealPersonService.updateCDealPerson(dealPerson);
        Assert.isTrue(i1 == 1, "更新交易记录失败");

        return orderId;
    }


    @Override
    @RecordOpeate(desc = "个人钱包小订单加注")
    public Object getMinOrder(Long orderId) throws IOException {
        // 标志来控制任务是否继续执行
        boolean continueTask = false;

        // 标志来控制任务是否继续执行
        boolean continueTaskIsNull = true;

        boolean bigOrderTask = false;

        int count = 0;

        //小订单长度
        int minOrderLength = 0;

        String result = null;
        while (continueTaskIsNull) {
            count++;
            try {
                String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
                result = apiService.findOrderDetailByOrderId(orderId, token);
                if (count > 30) {
                    logger.info("付款未加注,超时自动退款---------数据为" + result);
                    redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                    continueTaskIsNull = false;
                }
                List<DataItem> dataItems = JsonParserExample.parseMinOrder(result);
                if (!dataItems.isEmpty()) {
                    continueTask = true;
                    continueTaskIsNull = false;
                }
                // 等待5秒
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break; // 如果线程被中断，退出循环
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        DataItem data = null;
        while (continueTask) {
            count++;
            try {
                String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
                result = apiService.findOrderDetailByOrderId(orderId, token);
                List<DataItem> dataItems = JsonParserExample.parseMinOrder(result);

                if (dataItems.isEmpty()) {
                    // 小订单数据从有到无,加注结束
                    logger.info("小订单数据从有到无,加注结束--------数据为" + data);
                    redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                    continueTask = false;

                } else {
                    data = dataItems.get(dataItems.size() - 1);
                    minOrderLength = dataItems.size();
                    logger.info("小订单信息正常,加注中---------最后一条数据为" + data);
                    // 异常情况，突然断电，或者人为停止
                    if (dataItems.size() == minOrderLength) {
                        // 等待10秒
                        logger.info("休眠30秒后再次查询小订单信息------------------");
                        Thread.sleep(30000);
                        result = apiService.findOrderDetailByOrderId(orderId, token);
                        dataItems = JsonParserExample.parseMinOrder(result);
                        if (dataItems.isEmpty()) {
                            // 第二次检查小订单数据为空，视为超时
                            logger.info(" 第二次检查小订单数据为空，加注结束" + data);
                            redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                            continueTask = false;
                        } else {
                            if (dataItems.size() == minOrderLength) {
                                logger.info("第二次检查小订单数据仍然未变化,加注完成---------最后一条数据为" + dataItems.get(dataItems.size() - 1));
                                redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                                continueTask = false;
                            } else {
                                // 小订单数据已更新
                                data = dataItems.get(dataItems.size() - 1);
                                minOrderLength = dataItems.size();
                                logger.info("小订单信息正常,加注中---------最后一条数据为" + data);
                            }
                        }
                    }
                }
                // 等待2秒
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break; // 如果线程被中断，退出循环
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        logger.info("查询大订单-----");
        String bigOrder = apiService.findByOrderId(orderId, redisCache.getCacheObject("token:" + "authorizerAccessToken"));
        BigDataItem bigDataItem = JsonParserExample.parseBigOrder(bigOrder);
        if (apiService.isWorking(bigDataItem)) {
            bigOrderTask = true;
            while (bigOrderTask) {
                try {
                    logger.info("查询大订单-----");
                    bigOrder = apiService.findByOrderId(orderId, redisCache.getCacheObject("token:" + "authorizerAccessToken"));
                    bigDataItem = JsonParserExample.parseBigOrder(bigOrder);
                    if (!apiService.isWorking(bigDataItem)) {
                        Thread.sleep(5000);
                        bigOrder = apiService.findByOrderId(orderId, redisCache.getCacheObject("token:" + "authorizerAccessToken"));
                        bigDataItem = JsonParserExample.parseBigOrder(bigOrder);
                        bigOrderTask = false;
                    }
                    // 等待10秒
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break; // 如果线程被中断，退出循环
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        System.out.println("大订单信息:" + bigDataItem);



        logger.info("将订单信息存入数据库-----");
        // 将订单信息存入数据库 更新数据库确保数据一致性
        CDeviceOrders cDeviceOrders = new CDeviceOrders();
        cDeviceOrders.setFillerId(orderId.toString());
        List<CDeviceOrders> realOrders = cDeviceOrdersService.selectCDeviceOrdersList(cDeviceOrders);
        if (realOrders.isEmpty()) {
            Assert.notNull(realOrders, "实际订单不存在");
        }
        CDeviceOrders realOrder = realOrders.get(0);
        realOrder.setOrderFilled(bigDataItem.getOrderVolReal());
        realOrder.setOrderFilledMoney(bigDataItem.getOrderMoneyReal());
        realOrder.setOrderMoney(bigDataItem.getOrderMoney());
        cDeviceOrdersService.updateCDeviceOrders(realOrder);

        logger.info("结算找零-----");
        //结算找零
        //TODO 个人用户找零
        //更新钱包
        logger.info("更新钱包-----");

        fillService.updateCWalletPerson(realOrder.getDeviceOrderId(), (long) (bigDataItem.getOrderVol() * 1000), bigDataItem.getOrderVolReal());
        //更新交易记录
        fillService.updateCDealPerson(realOrder.getDeviceOrderId(), bigDataItem.getOrderVolReal());

        logger.info("更新需求订单-----");
        //更新需求订单
        CRequirement cRequirement = requirementService.selectCRequirementByRequireId(realOrder.getRequireId());
        if (cRequirement != null) {
            cRequirement.setStatus(2);
            requirementService.updateCRequirement(cRequirement);
        }
        return null;
    }

}
